﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using P3SS.Networking;
using P3SS.Engine;

namespace P3SS.Settings
{
	/// <summary>
	/// Manages importing of settings from a CSV file
	/// </summary>
	public static class CsvImporter
	{
		/// <summary>
		/// Imports settings from a CSV file
		/// </summary>
		/// <param name="filename">Name of the CSV file to load</param>
		/// <param name="defaultAccount">Default settings for an account</param>
		/// <returns>The list of accounts imported</returns>
		public static List<Account> ImportFromCSV(string filename, Account defaultAccount)
		{
			FileInfo csvFileInfo = new FileInfo(filename);
			List<Account> importedAccounts = new List<Account>();
			FileStream csvStream = csvFileInfo.Open(FileMode.Open, FileAccess.Read);
			StreamReader sr = new StreamReader(csvStream);

			string firstLine = sr.ReadLine();
			string[] headers = firstLine.ToLower().Split(new char[] { ',' });

			while (!sr.EndOfStream)
			{
				Account thisAccount = new Account(defaultAccount);
				string thisLine = sr.ReadLine();
				string[] lineElements = thisLine.Split(new char[] { ',' });

				int counter = 0;
				while ((counter < headers.Length) && (counter < lineElements.Length))
				{
					if (lineElements[counter] != "")
					{
						switch (headers[counter])
						{
							case "pop3username":
								thisAccount.Pop3Account.Username = lineElements[counter];
								break;
							case "pop3password":
								thisAccount.Pop3Account.Password = lineElements[counter];
								break;
							case "pop3address":
								thisAccount.Pop3Account.Server = lineElements[counter];
								break;
							case "pop3port":
								int pop3port;
								if (Int32.TryParse(lineElements[counter], out pop3port))
									thisAccount.Pop3Account.Port = pop3port;
								break;
							case "pop3leavemessages":
								thisAccount.Pop3Account.LeaveMailOnServer = convertStringToBool(lineElements[counter], thisAccount.Pop3Account.LeaveMailOnServer);
								break;
							case "pop3apop":
								thisAccount.Pop3Account.UseAPOP = convertStringToBool(lineElements[counter], thisAccount.Pop3Account.UseAPOP);
								break;
							case "pop3encryption":
								thisAccount.Pop3Account.Encryption = convertStringToEnum(lineElements[counter], thisAccount.Pop3Account.Encryption);
								break;
							case "smtpaddress":
								thisAccount.SmtpAccount.Server = lineElements[counter];
								break;
							case "smtpport":
								int smtpport;
								if (Int32.TryParse(lineElements[counter], out smtpport))
									thisAccount.SmtpAccount.Port = smtpport;
								break;
							case "smtpforwardto":
								thisAccount.SmtpAccount.ToFilter = convertStringToEnum(lineElements[counter], thisAccount.SmtpAccount.ToFilter);
								switch (thisAccount.SmtpAccount.ToFilter)
								{
									case EmailToFilter.SpecificAddress:
										thisAccount.SmtpAccount.DomainFilter = "";
										break;
									case EmailToFilter.FilterDomain:
										thisAccount.SmtpAccount.EmailAddress = "";
										break;
									case EmailToFilter.AllToHeaders:
										thisAccount.SmtpAccount.EmailAddress = "";
										thisAccount.SmtpAccount.DomainFilter = "";
										break;
								}
								break;
							case "smtpemailaddress":
								thisAccount.SmtpAccount.EmailAddress = lineElements[counter];
								break;
							case "smtpdomainfilter":
								thisAccount.SmtpAccount.DomainFilter = lineElements[counter];
								break;
							case "smtpencryption":
								thisAccount.SmtpAccount.Encryption = convertStringToEnum(lineElements[counter], thisAccount.SmtpAccount.Encryption);
								break;
						}
					}

					counter++;
				}

				if ((thisAccount.SmtpAccount.ToFilter == EmailToFilter.FilterDomain) && (thisAccount.SmtpAccount.DomainFilter == ""))
				{
					thisAccount.SmtpAccount.ToFilter = EmailToFilter.AllToHeaders;
				}

				importedAccounts.Add(thisAccount);
			}

			sr.Close();

			return importedAccounts;
		}

		private static bool convertStringToBool(string inString, bool defaultValue)
		{
			string lowerInString = inString.ToLower();
			
			bool result = defaultValue;
			if ((lowerInString == "y") || (lowerInString == "1") || (lowerInString == "true"))
			{
				result = true;
			}
			else if ((lowerInString == "n") || (lowerInString == "0") || (lowerInString == "false"))
			{
				result = false;
			}

			return result;
		}

		private static T convertStringToEnum<T>(string inString, T defaultValue) where T : struct
		{
			string lowerString = inString.ToLower();
			string foundName = "";
			T result = defaultValue;
			string[] enumNames = Enum.GetNames(typeof(T));

			int counter = 0;
			while ((foundName == "") && (counter < enumNames.Length))
			{
				if (enumNames[counter].ToLower() == lowerString)
				{
					foundName = enumNames[counter];
				}
				counter++;
			}

			try
			{
				result = (T)(Enum.Parse(typeof(T), foundName));
			}
			catch { }

			return result;
		}
	}
}
